/*********************************************************************************
 *      Copyright:  (C) 2022 SCEUC
 *                  All rights reserved.
 *
 *       Filename:  eLoRa.c
 *    Description:  This file is used for tlv 
 *                 
 *        Version:  1.0.0(2022年07月22日)
 *         Author:  Zhang.Kang <13874854275@163.com>
 *      ChangeLog:  1, Release initial version on "2022年07月22日 16时24分35秒"
 *                 
 ********************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include "eLoRa.h"
#include "cJSON.h"
#include "parson.h"



/*
 * func: Parse the data uploaded by the sLoRa node.
 * para:
 *      input: sp is the sLoRa data.
 *      output: ep is used to save data of parsing.
 * return:
 *      success: 0
 *      failed : -1
 **/
int parse_sLoRa(mqtt_pack_t *ep,uint8_t *sp)
{
    if(ep == NULL || sp == NULL)
    {
        return -1;
    }

    ep->netaddr = (int)(sp[0] << 8) | sp[1];
    ep->devaddr = (int)sp[2];
    ep->battery = (int)sp[3];
    ep->devtype = (int)sp[4];

    if(sp[5] & 0x80)
    {
        sprintf(ep->temp,"-%d.%d",sp[5] & 0x7f,sp[6]);
    }
    else
    {
        sprintf(ep->temp,"%d.%d",sp[5] & 0x7f,sp[6]);
    }

    sprintf(ep->humi,"%d.%d",sp[7],sp[8]);

    return 0;

}


/*
 * func: Package the data into JSON packages.
 * para: 
 *      input: ep saved data to be packaged.
 *      output:none
 * return:
 *      success: Returns a pointer to a JSON structure.
 *      failed : NULL
 **/
char *mqtt_pack_json(mqtt_pack_t *ep)
{
    cJSON *root;
    char *p;


    if(ep == NULL)
    {
        return NULL;
    }

    p = (char *)malloc(sizeof(char));

    root = cJSON_CreateObject();

    cJSON_AddItemToObject(root,"time",cJSON_CreateString(ep->time));
    cJSON_AddItemToObject(root,"netaddr",cJSON_CreateNumber(ep->netaddr));
    cJSON_AddItemToObject(root,"devaddr",cJSON_CreateNumber(ep->devaddr));
    cJSON_AddItemToObject(root,"battery",cJSON_CreateNumber(ep->battery));
    cJSON_AddItemToObject(root,"devtype",cJSON_CreateNumber(ep->devtype));
    cJSON_AddItemToObject(root,"rssi   ",cJSON_CreateNumber(ep->rssi));
    cJSON_AddItemToObject(root,"temperature",cJSON_CreateString(ep->temp));
    cJSON_AddItemToObject(root,"humidity",cJSON_CreateString(ep->humi));

    p = cJSON_Print(root);

    return p;

}


/*
 * func: Prase the broker server configuration file.
 * para: 
 *      input: conf_file is path of configuration file.
 *      output: mb is used to save parameters of configuration.
 * return:
 *      success: 0
 *      failed: -1
 **/
int parse_broker_configuration(const char *conf_file,mqtt_broker_t *mb)
{
    const char conf_obj_name[] = "emqx_conf";
    JSON_Value *root_val;
    JSON_Value *val = NULL;
    JSON_Object *conf_obj = NULL;
    JSON_Array *conf_array = NULL;
    const char *str = NULL;
    char *stop = NULL;
    int i = 0;

    /*  try to parse JSON */
    root_val = json_parse_file_with_comments(conf_file);
    if (root_val == NULL)
    {
        printf("ERROR: %s is not a valid JSON file\n", conf_file);
        return -1;
    }

    /*point to the gateway configuration object */
    conf_obj = json_object_get_object(json_value_get_object(root_val), conf_obj_name);
    if (conf_obj == NULL) 
    {
        printf("ERROR: %s does not contain a JSON object named %s\n", conf_file, conf_obj_name);
        return -1;
    } 
    else 
    {
        printf("INFO: %s does contain a JSON object named %s, parsing gateway parameters\n", conf_file, conf_obj_name);
    }

    /*  gateway unique identifier (aka MAC address) (optional) */
    str = json_object_get_string(conf_obj, "host");
    if (str == NULL) 
    {
        printf("ERROR: not found host\n");
        return -1;
    }
    else
    {
        strncpy(mb->host,str,sizeof(mb->host));
    }

    val = json_object_get_value(conf_obj, "port");
    if(val == NULL) 
    {  
        printf("ERROR: not found port\n");
        return -1;
    }  
    else
    {  
        mb->port = (int)json_value_get_number(val);
    }

    val = json_object_get_value(conf_obj, "keepalive_interval");
    if(val == NULL)
    {
        printf("ERROR: not found keepalive_interval\n");
        return -1;
    }
    else
    {
        mb->keepalive = (int)json_value_get_number(val);
    }

    str = json_object_get_string(conf_obj, "username");
    if (str == NULL)
    {
        printf("ERROR: not found username\n");
        return -1;
    }
    else
    {
        strncpy(mb->username,str,sizeof(mb->username));
    }

    str = json_object_get_string(conf_obj, "password");
    if (str == NULL)
    {
        printf("ERROR: not found password\n");
        return -1;
    }
    else
    {
        strncpy(mb->password,str,sizeof(mb->password));
    }

    conf_array = json_object_get_array(conf_obj, "network");
    if(conf_array == NULL)
    {
        printf("ERROR: not found network\n");
        return -1;
    }
    else
    {
        mb->network_size = json_array_get_count(conf_array);
        for(i = 0; i < mb->network_size; i++)
        {

            val = json_array_get_value(conf_array, i);
            if(val == NULL)
            {
                printf("network array not element\n");
                return -1;
            }
            if(i < NETWORK_SIZE)
            {
                mb->network[i] = (int)json_value_get_number(val);
            }
    
        }
    }

    str = json_object_get_string(conf_obj, "header");
    if (str == NULL)
    {
        printf("ERROR: not found header\n");
        return -1;
    }
    else
    {
        mb->header = strtol(str,&stop,16);
    }


    return 0;


}

/*
 * func: Connect to mqtt broker server.
 * para:
 *      input: mb is saved parameters of configuring broker.
 *      ouput: mosq is operation handler of broker.
 * return:
 *      success:0
 *      failed: -1
 * */
int mqtt_broker_connect(mqtt_broker_t mb,struct mosquitto **mosq)
{
    int loop = -1;
    int rv;

    if(NULL == mosq)
    {
        return -1;
    }

    mosquitto_lib_init();
    *mosq = mosquitto_new(NULL,true,NULL);
    if(*mosq == NULL)
    {
        printf("Create mqtt client failed:%s\n",strerror(errno));
        mosquitto_lib_cleanup();
        return -1;
    }

    rv = mosquitto_username_pw_set(*mosq,mb.username,mb.password);
    if(rv != MOSQ_ERR_SUCCESS)
    {
        printf("Set mqtt broker user data failed\n");
        goto Cleanup;
    }

    if(mosquitto_connect(*mosq,mb.host,mb.port,mb.keepalive))
    {
        printf("Unable to connect mqtt broker:%s\n",strerror(errno));
        goto Cleanup;
    }

    loop = mosquitto_loop_start(*mosq);
    if(loop != MOSQ_ERR_SUCCESS)
    {
        printf("mosquitto loop error:%s\n",strerror(errno));
        goto Cleanup;
    }


    return 0;

Cleanup:
    mosquitto_destroy(*mosq);
    mosquitto_lib_cleanup();
    return -1;
}

/*
 * func: Judage if sLoRa is in a network.
 * para:
 *      input: arr is saved network num.
 *      input: size is arr size.
 *      input: e is network of sLoRa.
 * return:
 *      yes: 1
 *      no : 0
 **/
int judge_network(int *arr,int size,int e)
{
    int i = 0;

    for(i = 0; i < size; i++)
    {
        if(arr[i] == e)
        {
            return 1;
        }
    }

    return 0;
}



